package cn.juque.systemservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.juque.common.constants.MessageEnum;
import cn.juque.common.constants.StringConstants;
import cn.juque.common.constants.TreeNodeConstants;
import cn.juque.common.exception.AppException;
import cn.juque.systemservice.api.constant.SystemServiceMsgEnum;
import cn.juque.systemservice.cache.OrgCache;
import cn.juque.systemservice.domain.OrgInfoDO;
import cn.juque.systemservice.entity.OrgInfo;
import cn.juque.systemservice.mapper.OrgInfoMapper;
import cn.juque.systemservice.service.IOrgInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author JUQUE
 * @version 1.0.0
 * <ul>
 *  <li>simple-generator</li>
 *  <li>机构信息</li>
 * </ul>
 * @date 2022-11-03 23:57:34
 **/
@Service("orgInfoService")
public class OrgInfoServiceImpl implements IOrgInfoService {

    @Resource
    private OrgInfoMapper orgInfoMapper;

    @Resource
    private OrgCache orgCache;


    /**
     * 查询
     *
     * @param orgInfo orgInfo
     * @return List
     */
    @Override
    public List<OrgInfoDO> listInfoWithoutPage(OrgInfo orgInfo) {
        OrgInfoDO orgInfoDO = new OrgInfoDO();
        BeanUtil.copyProperties(orgInfo, orgInfoDO);
        return this.orgInfoMapper.queryInfoList(orgInfoDO);
    }

    /**
     * 详情
     *
     * @param id 主键
     * @return OrgInfo
     */
    @Override
    public OrgInfoDO detail(String id) {
        OrgInfo orgInfo = this.orgInfoMapper.selectById(id);
        OrgInfoDO orgInfoDO = new OrgInfoDO();
        BeanUtil.copyProperties(orgInfo, orgInfoDO);
        if (TreeNodeConstants.ROOT_CHAR.equals(orgInfoDO.getParentOrgId())) {
            orgInfoDO.setParentOrgName(TreeNodeConstants.ROOT_NAME);
        } else {
            OrgInfo parent = this.orgInfoMapper.selectById(orgInfoDO.getParentOrgId());
            orgInfoDO.setParentOrgName(parent.getOrgName());
        }
        return orgInfoDO;
    }

    /**
     * 多主键获取
     *
     * @param orgIdList    主键列表
     * @return list
     */
    @Override
    public List<OrgInfoDO> getByIds(List<String> orgIdList) {
        Map<String, OrgInfoDO> orgMap = orgIdList.stream()
                .map(t -> this.orgCache.get(t)).collect(Collectors.toMap(OrgInfo::getOrgId, t -> t, (k1, k2) -> k2));
        return CollUtil.newArrayList(orgMap.values());
    }

    /**
     * 保存
     *
     * @param orgInfo orgInfo
     */
    @Override
    public void saveInfo(OrgInfo orgInfo) {
        // 校验id是否重复.
        if (null != this.orgInfoMapper.selectById(orgInfo.getOrgId())) {
            throw new AppException(SystemServiceMsgEnum.ORG_CODE_EXIST);
        }
        // 计算机构级次,机构级次码
        if (TreeNodeConstants.ROOT_CHAR.equals(orgInfo.getParentOrgId())) {
            orgInfo.setOrgLevel(1);
            orgInfo.setOrgLevelCode(orgInfo.getOrgId());
        } else {
            OrgInfo parenSysOrg = this.orgInfoMapper.selectById(orgInfo.getParentOrgId());
            if (parenSysOrg == null) {
                throw new AppException("保存失败,上级机构ID【" + orgInfo.getParentOrgId() + "】不存在!");
            }
            orgInfo.setOrgLevel(parenSysOrg.getOrgLevel() + 1);
            orgInfo.setOrgLevelCode(parenSysOrg.getOrgLevelCode() + StringConstants.VERTICAL_LINE + orgInfo.getOrgId());
        }
        this.orgInfoMapper.insert(orgInfo);
    }

    /**
     * 更新
     *
     * @param orgInfo orgInfo
     */
    @Override
    public void updateInfo(OrgInfo orgInfo) {
        boolean flag = SqlHelper.retBool(this.orgInfoMapper.updateById(orgInfo));
        if (!flag) {
            throw new AppException(MessageEnum.UPDATE_FAIL);
        }
    }

    /**
     * 删除
     *
     * @param ids 主键列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInfo(List<String> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        for (String orgId : ids) {
            if (this.isHasChildOrg(orgId)) {
                throw new AppException(MessageEnum.DELETE_FAIL.getCode(), "[" + orgId + "]存在下级机构");
            }
        }
        int count = this.orgInfoMapper.deleteBatchIds(ids);
        if (count != ids.size()) {
            throw new AppException(MessageEnum.DELETE_FAIL);
        }
    }

    /**
     * 是否有下级机构
     *
     * @param orgId 机构id
     * @return boolean
     */
    private boolean isHasChildOrg(String orgId) {
        OrgInfo orgInfo = new OrgInfo();
        orgInfo.setParentOrgId(orgId);
        Long count = this.orgInfoMapper.selectCount(new QueryWrapper<>(orgInfo));
        return SqlHelper.retBool(count);
    }

}
